#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include "pthread.hpp"
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static const int gnum = 5;
template <typename T>
class ThreadPool
{
public:
    ThreadPool(int num = gnum) : _num(num)
    {
        for (int i = 0; i < num; i++)
        {
            _threads.emplace_back([this]()
                                  { this->HandlerTask(); });
        }
    }
    void Start()
    {
        for (auto &thread : _threads)
        {
            thread.Start();
        }
    }
    void PushTask(const T &task)
    {
        pthread_mutex_lock(&mutex);
        _taskq.push(task);
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
    void HandlerTask()
    {
        char name[128];
        pthread_getname_np(pthread_self(), name, sizeof(name));
        while (true)
        {
            T t;
            {
                pthread_mutex_lock(&mutex);
                while (_taskq.empty())
                {
                    pthread_cond_wait(&cond, &mutex);
                }
                // 一定有任务
                t = _taskq.front(); // 从q中获取任务，任务已经是线程私有的了！！！
                _taskq.pop();
                pthread_mutex_unlock(&mutex);
            }
            t(); // 处理任务，需要在临界区内部处理吗？1 0
        }
    }
    ~ThreadPool()
    {
    }

private:
    std::vector<Thread> _threads;
    int _num; // 线程池中，线程的个数
    std::queue<T> _taskq;
};
